Portée des variables

Les variables ont différentes importances dans la réalisation d'un programme. Une variable peut porter une information cruciale tandis qu'une autre peut-être juste une variable temporaire sans grande importance, (comme l'indice dans une boucle). Autre exemple, les arguments d'une fonction que l'on déclare n'existent pas en dehors de la fonction elle-même. On parle dans ces cas d'une portée locale.

IVariable locale

Une variable est dite locale si elle n'existe que dans la fonction où elle est définie.
  • Créer un fichier test_variables.py dans lequel nous allons pouvoir tester la portée de variables.

  • Tapez et exécutez le code suivant :

    def ma_fonction(a):
        b=a+2
        print("variables dans la fonction : %i, %i" %(a,b))
        print([a,b])

    ma_fonction(12)
    print("variables hors de la fonction : %i, %i" %(a,b))
    Que remarque t'on pour a et b ?

  • Modifiez le programme en ajoutant avant la fonction la ligne suivante :

    a,b = 100,1000
    Que remarque t'on pour a et b ?

    Un peu plus subtil : enlever l'argument à la fonction et affecter 12 à a dans la fonction. Le programme doit ressembler à ceci :

    a,b=100,1000
    def ma_fonction():
        a=12
        b=a+2
        print("variables dans la fonction : %i, %i" %(a,b))
        print([a,b])

    ma_fonction(12)
    print("variables hors de la fonction : %i, %i" %(a,b))
    Que remarque t'on ?

Si maintenant vous refaites les trois questions précédentes, la première ne donnera plus d'erreur car les variables a et b auront été créées. Pour remettre à zéro, vous pouvez les effacter en tapant dans la console del(a) et del(b) .
  • Les variables a et b sont locales : n'ayant été déclarées qu'à l'intérieur de la fonction, elles n'existent pas en dehors.
  • Si a et b sont déclarés à l'extérieur de la fonction, leur utilisation comme comme variable locale ne modifie pas leur valeur en dehors. Leurs valeurs ont été sauvegardées.
  • Une variable définie en dehors de la fonction continue d'exister à l'intérieur de celle-ci. Par contre aucune modification n'est prise en compte.

IIVariable globale

Une variable est dite globale si elle existe et est modifiable dans tout le programme.

Nous avons vu dans la partie précédente qu'une variable initialisée à l'extérieur d'une fonction est toujours utilisable, mais non modifiable à l'intérieur d'une fonction. C'est un parti pris de Python, quand il ne trouve de variable dans l'espace local de la fonction, il va la chercher en dehors, sans modification autorisée.

Pour préciser à Python qu'une variable a est globale, il faut le préciser à l'intérieur de la fonction qui l'utilise en ajoutant la ligne global a .

Reprenez le programme précédent et modifiez le pour que la variable a soit globale pour la fonction ma_fonction() .

Le programme doit ressembler à ceci :
a,b=100,1000
def ma_fonction():
    global a
    a=12
    b=a+2
    print("variables dans la fonction : %i, %i" %(a,b))
    print([a,b])

ma_fonction(12)
print("variables hors de la fonction : %i, %i" %(a,b))
Maintenant la variable a est modifiée dans l'espace global.

IIIRéférence

En Python, les variables ne "contiennent" par vraiment les valeurs qu'on leur affecte. En réalité, elle pointent vers une référence de la valeur.

Une référence est une adresse mémoire permettant à Python de retrouver une valeur mise en mémoire.

La fonction id() permet d'afficher l'adresse de l'objet auquel fait référence une variable.
Dans la console, tapez les commandes suivantes :
  • a=1
  • b=a
  • id(a)==id(b)
  • a=2
  • b
  • id(a)==id(b)
Les références permettent notamment à Python de faire une utilisation intelligente et économe de la mémoire. On observe qu'au départ, l'affectation b=a n'a pas créé un nouvel objet numérique en mémoire, mais s'est contenter donner la même référence aux deux variables a et b . À la modification de a , un nouvel objet est mis en mémoire et la référence change.
Pour l'instant, ce niveau de détail peut semnbler inutile au programmeur, mais une bonne compréhension des références est importante pour les objets complexes tels que les listes :
Dans la console, tapez les commandes suivantes :
  • L1=[1,2,3]
  • L2=L1
  • L1[0]=9999
  • L1
  • L2
Qu'observe-t'on ? Que dire des références de L1 et L2 ?
Les références n'ont pas changé, et la modification d'une variable semble entraîner la modification de l'autre. En fait, il s'agit simplement de deux noms de variables différents faisant référence au même objet en mémoire.
Une liste est un objet faisant référence à un certain nombre de sous objets en mémoire. Ce n'est pas en modifiant l'un d'eux que le nom de la variable faisant référence à la liste est modifié. Les types simples int , float , string et bool ne sont pas modifiables comme une liste (sauf par une affectation qui casse la référence).
Pour recopier vraiment une liste L1 et l'affecter à une variable L2 , il faut taper :
L2=list(L1)
Les modifications de L1 et L2 seront indépendantes.
  • Nous allons reprendre et modifier le fichier test_variables.py pour tester la portée de variables de type liste.

  • Tapez et exécutez le code suivant :

    L=[1,2,3] def ma_fonction(L):
        L=[4,5]
        print(L)

    ma_fonction(L)
    print(L)
    Que remarque t'on ?

  • Cette fois, dans la fonction, nous n'allons pas affecter une nouvelle valeur à la liste L , mais la modifier.

    L=[1,2,3] def ma_fonction(L):
        L[0]=9999
        del(L[1])
        print(L)

    ma_fonction(L)
    print(L)
    Que remarque t'on ? La variable L est-elle globale ?

  • Il n'y a aucune différence avec le cas précédent : la liste n'est pas traité différemment d'une variable numérique : affecter une nouvelle valeur dans l'espace local à la fonction n'a pas d'incidence sur la valeur de L dans l'espace global.
  • La différence peut sembler subtile : nous n'avons pas affecté une nouvelle valeur à L dans la fonction, mais effectué des modifications sur ses sous-éléments. Ceux-ci sont donc modifiés, mais pas la référence de L .